﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;

namespace ModbusTestTool
{

    public abstract class BaseRegisterGeneric<T> : BaseRegister
    {


        void setupdelegate(){
            //Type[] typeofstring = new Type[1];
            //typeofstring[0] = typeof(string);
            //parse = Delegate.CreateDelegate(typeof(T).GetMethod("Parse"),typeof(T).GetMethod("Parse", new [] {typeof(string)}), );
            //MethodInfo method = typeof(T).GetMethod("Parse", new[] { typeof(string) });

            

            //parse = Delegate.CreateDelegate(typeof(T),

            parse = Delegate.CreateDelegate(typeof(Func<String, T>), typeof(T).GetMethod("Parse", new[] { typeof(string) }));
            
            
           //parse = Delegate.CreateDelegate(typeof(T),typeof(string), typeof(T).GetMethod("Parse", new[] { typeof(string) }));
            //parse = Delegate.CreateDelegate(
        }
        /// <summary>
        /// An method that will be initiallized to parse the data based on data type
        /// </summary>
        Delegate parse;// = Delegate.CreateDelegate(typeof(T).GetMethod("Parse",).GetType(), typeof(T).GetMethod("Parse"));
        //Func<T, string> parseFunction = typeof(T).GetMethod("Parse").

        /// <summary>
        /// This variable is there for sincronization purposes
        /// </summary>
        protected object lockVariable = new object();
        


        protected T m_result;


        public T result
        {
            get
            {
                lock (lockVariable)
                {
                    return m_result;
                }
            }
            set
            {
                lock (lockVariable)
                {
                    m_result = value;
                }
            }
        }

        /// <summary>
        /// Default constructor just makes sure the dirty bit is false
        /// </summary>
        public BaseRegisterGeneric()
        {
            dirty = false;
        }
        /// <summary>
        /// Constructor takes list of string and then populates rest of fields
        /// currently the size of list should should be 3
        /// register name,register number, floating or word (w/f)
        /// </summary>
        /// <param name="words">a list of strings ito the class</param>
        public BaseRegisterGeneric(string inParamName, int inRegister)
        {
            dirty = false;
            paramName = inParamName;

            //parse the Address
            register = inRegister;

            parseRegisterType();

            //parseRegisterDataType(words);
            
            if (registerType == regType.holding)
            {
                baseRegister = (ushort)(register - 40000);
            }

            if (registerType == regType.input)
            {
                baseRegister = (ushort)(register - 30000);
            }
            setupdelegate();

        }

        
        /// <summary>
        /// Method is used but this method would read a type
        /// </summary>
        /// <param name="words">array item 3 contain f/w for float or word</param>


        private void parseRegisterType()
        {
            if (register >= 40000)
            {
                registerType = regType.holding;
            }
            else
            {
                registerType = regType.input;
            }

        }

        //public abstract void setValue(ushort[] foo);
        //public abstract void getValue(ushort[] foo);


        //public abstract int size { get; }



        public override string value
        {
            get
            {
                lock (lockVariable)
                {
                    return m_result.ToString();
                }
            }
            set
            {
                lock (lockVariable)
                {
                    m_result = (T)parse.DynamicInvoke(value);
                    dirty = true;
                }
            }
        }
    }
}
